package com.happy3w.ssp.schoolmatehome.service.auth;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.StringUtils;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Optional;

@NoArgsConstructor
@Getter
@Setter
public class JwtToken {
    public static final long EXPIRATION_TIME = 3 * 24 * 60 * 60 * 1000; // 3天
    private static final byte[] SECRET_BYTES = new byte[]{
            -41, 92, -57, 5, 35, -84, 49, -56, 45, -9, -43, -12, -34, -1, 56, 80, -80, -105, -106, 4, 29, 109, -41,
            74, 91, -13, 123, 1, 84, 105, 84, -81};
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SECRET_BYTES);

    private String subject;
    private long expirationTime;

    public JwtToken(String subject, long expirationTime) {
        this.subject = subject;
        this.expirationTime = expirationTime - expirationTime % 1000;
    }


    public String encode() {
        return Jwts.builder()
                .subject(subject)
                .expiration(new Date(expirationTime))
                .signWith(SECRET_KEY)
                .compact();
    }

    public boolean isValid() {
        return expirationTime > System.currentTimeMillis();
    }

    public static Optional<JwtToken> decode(String token) {
        if (!StringUtils.hasLength(token)) {
            return Optional.empty();
        }
        try {
            Claims payload = Jwts.parser()
                    .verifyWith(SECRET_KEY)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
            return Optional.of(new JwtToken(payload.getSubject(), payload.getExpiration().getTime()));
        } catch (Exception e) {
            return Optional.empty();
        }
    }

    public static JwtToken of(String subject) {
        return new JwtToken(subject, System.currentTimeMillis() + EXPIRATION_TIME);
    }

    public static JwtToken extract(String head) {
        if (head != null && head.startsWith("Bearer ")) {
            head = head.substring(7);
            return JwtToken.decode(head)
                    .filter(JwtToken::isValid)
                    .orElse(null);
        }
        return null;
    }
}
